package com.lingnan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lingnan.entity.po.Blacklist;
import com.lingnan.entity.vo.Result;
import com.lingnan.exception.MyException;
import com.lingnan.mapper.BlacklistMapper;
import com.lingnan.redis.RedisUtil;
import com.lingnan.service.BlacklistService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class BlacklistServiceImpl
        extends ServiceImpl<BlacklistMapper, Blacklist>
        implements BlacklistService {

    private final RedisUtil redisUtil;
    private static final String BLACKLIST_KEY = "blacklist:";

    public BlacklistServiceImpl(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    @Transactional
    @Override
    public Result addBlacklist(Blacklist blacklist) {
        // 依赖注入ObjectMapper（需在类中添加）
        final ObjectMapper objectMapper = new ObjectMapper(); // 建议通过构造函数注入

        // 检查是否已存在相同拉黑关系
        boolean exists = baseMapper.exists(new LambdaQueryWrapper<Blacklist>()
                .eq(Blacklist::getSourceId, blacklist.getSourceId())
                .eq(Blacklist::getTargetId, blacklist.getTargetId())
                .eq(Blacklist::getTargetType, blacklist.getTargetType())
                .eq(Blacklist::getStatus, 1));

        if (exists) {
            throw new MyException("已存在相同的拉黑关系");
        }

        blacklist.setCreatedAt(new Date());
        save(blacklist);

        // 修复点：序列化对象+使用setNx+异常处理
        String cacheKey = buildCacheKey(blacklist.getSourceId(), blacklist.getTargetId());
        try {
            // 序列化为 JSON 字符串
            String jsonValue = objectMapper.writeValueAsString(blacklist); // 序列化为JSON String
            // 使用 setNx 防止覆盖（仅当 key 不存在时写入）
            boolean isSet = redisUtil.setNx(cacheKey, jsonValue, 24L, TimeUnit.HOURS);
            if (!isSet) {
                log.error("Redis缓存设置失败：键已存在。");
            }
        } catch (JsonProcessingException e) {
            // 使用支持异常链的构造方法
            throw new MyException("对象序列化失败", e);
        } catch (Exception e) {
            // 传递原始异常
            throw new MyException("Redis缓存操作异常", e);
        }
        return Result.ok(blacklist);
    }

    @Override
    //查询
    public Result getBlacklistPage(int page, int size, Long sourceId, Long targetId, Integer targetType, Integer status) {
        IPage<Blacklist> result = baseMapper.selectByCondition(
                new Page<>(page, size),
                sourceId,
                targetId,
                targetType,
                status);
        return Result.ok(result);
    }

    //删除
    @Override
    public Blacklist revokeBlacklist(Long id, Long operatorId) {
        Blacklist blacklist = (Blacklist) getById(id).getData();  // 复用getById的逻辑
        if (blacklist == null) {
            throw new MyException("黑名单记录不存在");
        }

        blacklist.setStatus(0);
        blacklist.setUpdateId(operatorId);
        updateById(blacklist);

        // 清除Redis缓存
        String cacheKey = buildCacheKey(blacklist.getSourceId(), blacklist.getTargetId());
        redisUtil.del(cacheKey);

        return blacklist;  // 直接返回实体
    }

    @Override
    public Result getById(Long id) {
        Blacklist blacklist = baseMapper.selectById(id);
        return blacklist != null ?
                Result.ok(blacklist) :
                Result.fail("黑名单记录不存在");
    }

    private String buildCacheKey(Long sourceId, Long targetId) {
        return BLACKLIST_KEY + sourceId + ":" + targetId;
    }
}
